#pragma once

#include <list>

#include "ir.h"

struct IRBlock {
    std::string name;
    std::list<IR::Phi*> phis;
    std::list<IR::IRBase*> irList;
    std::unordered_map<IRBlock*, IRBlock**> prev;

    IRBlock() {}
    IRBlock(IR::IRBase* ir) {
        irList.emplace_back(ir);
        ir->parent = this;
    }

    void Print() const;

    void AddPhi(IR::Phi* phi);
    void AddIR(IR::IRBase* ir);

    std::list<IR::IRBase*> GetAllIR() const;
    IR::Terminator* GetTerminator() const;
    std::vector<IRBlock*> GetNext() const;
    std::vector<IRBlock*> GetPrev() const;

    // Connect the block with another block using jump terminator.
    // Never do this in SSA form.
    void Connect(IRBlock* nxt);

    // Connect the block with another block using branch terminator.
    // Never do this in SSA form.
    void Connect(ArithOp op, IR::Operand* lhs, IR::Operand* rhs, IRBlock* t,
                 IRBlock* f);

    // Remove the block and connect the previous with the reserved block.
    // reserve = 0/1: reserve true/false condition block.
    IRBlock* Remove(int reserve = -1);

    // Change branch terminator into jump terminator.
    // reserve = 0/1: reserve true/false condition block.
    IRBlock* RemoveBranch(int reserve = -1);
};
